In [1]:
# Create a tuple directly
digits = (0, 1, 'two')
digits
Out[1]:
In [2]:
# Create a tuple from a list
digits = tuple([0, 1, 'two'])
digits
Out[2]:
In [3]:
# For a single item tuple, a trailing comma is required to tell the intepreter its a tuple
zero = (0,)
zero
Out[3]:
In [4]:
# elements of a tuple cannot be modified (this would throw an error)
# digits[2] = 2
In [5]:
#concatenate tuples
digits = digits + (3,4)
digits
Out[5]:
In [6]:
# Create a single tuple with elements repeated (also workss with lists)
(3, 4) * 2
Out[6]:
In [7]:
# sort a list of tuples
tens = [(20,60), (10,40), (20,30)]
sorted(tens) #sorts by first element in tuple, then second element
Out[7]:
In [8]:
bart = ('male', 10, 'simpson') # create a tuple
(sex, age, surname) = bart
print(sex)
print(age)
print(surname)
In [9]:
#use the star expression to load multiple values into a list
record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')
name, email, *phone_numbers = record
phone_numbers
Out[9]:
In [10]:
# star expressions can be used in the middle of the iterable too!
def drop_first_last(grades):
first, *middle, last = grades
return float(sum(middle)) / len(middle)
drop_first_last([3, 8, 8, 8, 8, 8,8, 100])
Out[10]:
In [11]:
# Tuples are compared by comparing their members in order
(3,9) < (5,3)
Out[11]:
In [12]:
(3,'banana') < (3,'apple')
Out[12]:
In [13]:
(3,'banana') == (3,'ban')
Out[13]:
In [14]:
# Tuple members are only compared if needed.
# Here is an uncomparable type
class mytype:
def go():
pass
a = mytype()
b = mytype()
(3, a) < (5,b)
Out[14]:
In [15]:
# but the folllowing code would generate an error because a and b would need to be evaluated
#(3,a) < (3,b)
collections.namedtuple() is a factory method that returns a subclass of the standard Python tuple type. You feed it a type name, and the fields it should have, and it returns a class that you can instantiate, passing in values for the fields you’ve defined, and so on.
In [3]:
from collections import namedtuple
Subscriber = namedtuple('Subscriber', ['addr','joined']) # namedtuple(<tuple-name>, [field1, field2, field3...])
jonesy = Subscriber('jonesy@example.com','2012-10-19')
jonesy
Out[3]:
In [4]:
len(jonesy)
Out[4]:
In [5]:
jonesy.addr
Out[5]:
In [6]:
# because a namedtuple is a tuple it is immutable.
# the following code would fail if uncommented
#jonesy.addr='another@example.com'
In [7]:
#instead, use replace()
jonesy = jonesy._replace(addr='another@example.com')
jonesy
Out[7]:
A subtle use of the _replace() method is that it can be a convenient way to populate named tuples that have optional or missing fields. To do this, you make a prototype tuple containing the default values and then use _replace() to create new instances with values replaced.
In [8]:
Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])
# Create a prototype instance
stock_prototype = Stock('', 0, 0.0, None, None)
# Function to convert a dictionary to a Stock
def dict_to_stock(s):
return stock_prototype._replace(**s)
a = {'name': 'ACME', 'shares': 100, 'price': 123.45}
dict_to_stock(a)
Out[8]:
In [9]:
b = {'name': 'ACME', 'shares': 100, 'price': 123.45, 'date': '12/17/2012'}
dict_to_stock(b)
Out[9]: